home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
.net (French) 1996 December
/
.net Magazine (FR) - Issue 02 - Dec 1996.iso
/
Utilpers
/
SUPERQUE
/
DATA.2
/
FILTERS
/
PSINIT
/
GS_SETPD.PS
< prev
next >
Wrap
Text File
|
1996-01-05
|
10KB
|
324 lines
% Copyright (C) 1994, 1995 Aladdin Enterprises. All rights reserved.
% Licensed to Zenographics Inc. (Irvine, California) by Artifex Software Inc.
% under the OEM Agreement of December 21st, 1993.
% The current implementation of setpagedevice has the following problems:
% - It doesn't save the CTM after the Install procedure as the
% one for initmatrix or defaultmatrix.
% - It doesn't interact properly with gsave/grestore.
% - It doesn't do the automatic 90 degree rotation if the PageSize
% dimensions need to be swapped.
% - It doesn't handle Policy values other than 1 or non-1.
languagelevel 1 .setlanguagelevel
level2dict begin
% Define currentpagedevice so it creates the dictionary on demand if needed.
% The only entry we add automatically is Policies.
/currentpagedevice
{ .currentpagedevice dup length 0 eq
{ pop currentdevice null .getdeviceparams
% In case of duplicate keys, .dicttomark takes the entry
% lower on the stack, so we can just append the defaults here.
/Policies .defaultpolicies .dicttomark
dup .setpagedevice
}
if
} bind odef
% The implementation of setpagedevice is quite complex. Currently,
% everything but the media matching algorithm is implemented here.
% Define the parameters that require special action to merge into the
% combined page device dictionary. The procedures are called as follows:
% <merged> <key> <new_value> -proc- <merged> <key> <new_value'>
/.mergespecial mark
/InputAttributes
{ dup null eq
{ pop null
}
{ 3 copy pop .knownget
{ dup null eq
{ pop dup length dict }
{ dup length 2 index length add dict copy }
ifelse
}
{ dup length dict
}
ifelse copy readonly
}
ifelse
} bind
/OutputAttributes 1 index
/Policies
{ 3 copy pop .knownget
{ dup length 2 index length add dict copy }
{ dup length dict }
ifelse copy readonly
} bind
.dicttomark readonly def
% Define the keys used in input attribute matching.
/.inputattrkeys [
/PageSize /MediaColor /MediaWeight /MediaType /InsertSheet
] readonly def
% Define the keys used in output attribute matching.
/.outputattrkeys [
/OutputType
] readonly def
% Define the parameters that should not be presented to the device.
% The procedures are called as follows:
% <merged> <key> <value> -proc-
% The procedure leaves all its operands on the stack and returns
% true iff the key/value pair should be presented to .putdeviceparams.
/.presentspecial mark
/Name false
/OutputDevice false
/InputAttributes false
.inputattrkeys { pop { 2 index /InputAttributes get null eq } } forall
/OutputAttributes false
.outputattrkeys { pop { 2 index /OutputAttributes get null eq } } forall
/Install false
/BeginPage false
/EndPage false
/Policies false
.dicttomark readonly def
% Define the required attributes of all page devices, and their default values.
% We don't include attributes such as PageSize, which all devices
% are guaranteed to supply on their own.
/.defaultpolicies mark
/PolicyNotFound 1
/PageSize 0
/PolicyReport {pop} bind
.dicttomark readonly def
/.requiredattrs mark
/InputAttributes mark 0 0 dict .dicttomark
/OutputAttributes mark 0 0 dict .dicttomark
/Install {.callinstall} bind
/BeginPage {.callbeginpage} bind
/EndPage {.callendpage} bind
/Policies .defaultpolicies
.dicttomark readonly def
% Define access to device defaults.
/.defaultdevicename 0 .getdevice .devicename def
/.defaultdeviceparams
{ finddevice null .getdeviceparams
} bind def
% Select media (input or output). The hard work is done in an operator:
% <pagedict> <attrdict> <keys> .matchmedia <key> true
% <pagedict> <attrdict> <keys> .matchmedia false
% <pagedict> null <keys> .matchmedia null true
/.selectmedia % <orig> <request> <merged> <failed>
% (these are retained)
% <attrdict> <attrkeys> <mediakey> .selectmedia
{ 4 index 4 -1 roll 3 index .matchmedia
{ 4 index 3 1 roll put pop
}
{ % Adobe's implementations have a "big hairy heuristic"
% to choose the set of keys to report as having failed the match.
% For the moment, we report any keys that are in the request
% and don't have the same value as in the original dictionary.
3 index exch undef
{ % Stack: <orig> <request> <merged> <failed> <attrkey>
3 index 1 index .knownget
{ 5 index 2 index .knownget { ne } { pop true } ifelse }
{ true }
ifelse % Stack: ... <failed> <attrkey> <report>
{ 2 copy /rangecheck put }
if pop
}
forall
}
ifelse
} bind def
% Apply Policies to any unprocessed failed requests.
% As we process each request entry, we replace the error name
% in the <failed> dictionary with the policy value,
% and we remove the key from the <merged> dictionary.
/.applypolicies % <merged> <failed> .applypolicies <merged'> <failed'>
{ 1 index /Policies get 1 index
{ type /integertype eq
{ pop % already processed
}
{ 2 copy .knownget not { 1 index /PolicyNotFound get } if
% Stack: <merged> <failed> <Policies> <key> <policy>
dup 1 ne
{ % Set errorinfo and signal a configurationerror.
% Note that we currently treat all Policy values other than 1
% the same as 0.
pop dup 4 index exch get 2 array astore
$error /errorinfo 3 -1 roll put
cleartomark
/setpagedevice load /configurationerror signalerror
}
{ % Ignore the failed request.
3 index 2 index 3 -1 roll put
3 index exch undef
}
ifelse
}
ifelse
}
forall pop
} bind def
% Try setting the device parameters from the merged request.
/.trysetparams % ... <merged> <(ignored)> <device> <Policies>
% .trysetparams
{ true mark 5 index dup
{ % Stack: <merged> <key> <value>
.presentspecial 2 index .knownget
{ exec { 3 -1 roll } { pop pop } ifelse }
{ 3 -1 roll }
ifelse
}
forall pop
DEBUG { (Putting.\n) print pstack flush } if
.putdeviceparams
DEBUG { (Result of putting.\n) print pstack flush } if
} bind def
% Finally, define setpagedevice.
/setpagedevice
{
mark exch currentpagedevice
% Check whether we are changing OutputDevice;
% also handle the case where the current device
% is not a page device.
% Stack: mark <request> <current>
DEBUG { (Checking.\n) print pstack flush } if
dup /OutputDevice .knownget
{ % Current device is a page device.
2 index /OutputDevice .knownget
{ % A specific OutputDevice was requested.
2 copy eq
{ pop pop null }
{ exch pop }
ifelse
}
{ pop null
}
ifelse
}
{ % Current device is not a page device.
% Use the default device.
1 index /OutputDevice .knownget not { .defaultdevicename } if
}
ifelse
dup null eq
{ pop
}
{ exch pop .defaultdeviceparams
% In case of duplicate keys, .dicttomark takes the entry
% lower on the stack, so we can just append the defaults here.
.requiredattrs { } forall .dicttomark
}
ifelse
% Merge the current and requested dictionaries.
% Stack: mark <request> <orig>
DEBUG { (Merging.\n) print pstack flush } if
exch 1 index dup length 2 index length add dict copy
dup 2 index
{ % stack: <orig> <request> <merged> <merged> <rkey> <rvalue>
.mergespecial 2 index .knownget { exec } if
put dup
}
forall pop
% Select input and output media.
% Stack: mark <orig> <request> <merged>
DEBUG { (Selecting.\n) print pstack flush } if
0 dict % <failed>
1 index /InputAttributes .knownget
{ .inputattrkeys (%MediaSource) cvn .selectmedia } if
1 index /OutputAttributes .knownget
{ .outputattrkeys (%MediaDestination) cvn .selectmedia } if
.applypolicies
% Construct the new device, and attempt to set its attributes.
% Stack: mark <orig> <request> <merged> <failed>
DEBUG { (Constructing.\n) print pstack flush } if
currentdevice .devicename 2 index /OutputDevice get eq
{ currentdevice }
{ 1 index /OutputDevice get finddevice }
ifelse
%**************** We should copy the device here,
%**************** but since we can't close the old device,
%**************** we don't. This is WRONG.
%****************copydevice
2 index /Policies get
.trysetparams
dup type /nametype eq
{ % The request failed.
% Stack: ... <failed> <device> <Policies> true mark
% <name> <errorname> ...
counttomark 5 add -1 roll
counttomark 2 idiv { dup 4 -2 roll put } repeat
exch pop 4 1 roll pop
% Stack: mark ... <merged> <failed> <device> <Policies>
4 2 roll .applypolicies 4 -2 roll
.trysetparams % shouldn't fail, except for /undefined
% Remove /undefined's
dup type /nametype eq
{ % The request failed.
% Stack: ... <failed> <device> <Policies> true mark
% <name> <errorname> ...
counttomark 5 add -1 roll
counttomark 2 idiv { dup 4 -2 roll put } repeat
exch pop 4 1 roll pop
% Stack: mark ... <merged> <failed> <device> <Policies>
4 2 roll .applypolicies 4 -2 roll
.trysetparams % shouldn't fail
}
if
dup type /booleantype ne
{ 2 { counttomark 1 add 1 roll cleartomark } repeat
/setpagedevice load exch signalerror
}
if
}
if
% The attempt succeeded. Install the new device.
% Stack: mark ... <merged> <failed> <device> <eraseflag>
DEBUG { (Installing.\n) print pstack flush } if
pop 2 .endpage
{ 1 true .outputpage
% (>>setpagedevice, press <return> to continue<<\n) .confirm
}
if
.setdevice pop
1 index /Install .knownget { exec } if
erasepage initgraphics
1 index .setpagedevice .beginpage
% Clean up, calling PolicyReport if needed.
% Stack: mark ... <merged> <failed>
DEBUG { (Finishing.\n) print pstack flush } if
dup length 0 ne
{ 1 index /Policies get /PolicyReport get
counttomark 1 add 2 roll cleartomark
exec
}
{ cleartomark
}
ifelse
} odef
end % level2dict
.setlanguagelevel